﻿using System;
using MessageSystem.Managed.Infrastructure;
using MessageSystem.Managed.Interface;

namespace MessageSystem.Managed.Rpc
{
    public class RpcHandler : IMessageHandler
    {
        protected IMessageChannel _channel;
        protected RpcBroadCaster  _broadCaster;
        public    IRpcRouter      Router { get; set; }

        public RpcHandler(IMessageChannel channel)
        {
            _channel = channel;
            if(null!=_channel)
                _channel.Open(this);
            _broadCaster = new RpcBroadCaster(this);
        }

        public void OnMsg(UInt16 nFlags,int nMessageId,int nSessionId,Int32 OpCode,NetStream ns)
        {
            short nServiceId = 0;
            short nMethodId = 0;
            RpcControl.MessageId2ServiceAndMethodId(nMessageId, ref nServiceId, ref nMethodId);

            if (nMessageId == RpcInnerMessage.RpcRouteRegisterMessageId)
            {
                if (null != Router)
                {
                    RpcRegisterMessage rMsg = new RpcRegisterMessage();
                    rMsg.Read(ns);
                    Router.Register(rMsg.SessionId, rMsg.ServiceId, this as RpcDomain);
                }
                return;
            }

            if (RpcControl.IsRpc(nFlags))
            {
                if (RpcControl.IsReturn(nFlags))
                {
                    RpcService service = GetService(nServiceId);
                    if (null != service)
                    {
                        service.InvokeProxy(nFlags, nMethodId, nSessionId,OpCode,ns);
                    }
                    else
                    {
                        if (null != Router)
                            Router.Route(nFlags, nMessageId, nSessionId, ns);
                    }
                }
                else
                {
                    RpcService service = GetService(nServiceId);
                    if (null != service)
                    {
                        service.InvokeService(nFlags, nMethodId, nSessionId,OpCode,ns);
                    }
                    else
                    {
                        if (null != Router)
                            Router.Route(nFlags, nMessageId, nSessionId, ns);
                    }
                }
            }
            else
            {
                if (null != Router)
                    Router.Route(nFlags, nMessageId, nSessionId, ns);
            }
        }

        protected virtual RpcService GetService(int serviceid) { return null; }
        public virtual void OnLost()
        {
            _channel = null;
        }

        internal virtual void Invoke(IMessage msg, UInt16 flags,int sessionid,Int32 OpCode)
        {
            if (null != _channel)
            {
                flags = RpcControl.SetRpc(flags);
                _channel.Send(msg, flags, sessionid, OpCode);
            }
        }

        public void Close()
        {
            if (null != _channel)
            {
                _channel.Close();
            }
            _channel = null;
        }
    }
}
